﻿using NPOI.SS.UserModel;
using NpoiSample.Helper.CompleteCustomer.Dto;
using System.Collections.Concurrent;

namespace NetByDocker.Core.Npoi.CompleteCustomer
{
    /// <summary>
    /// excel帮助类
    /// </summary>
    public static class ExcelHelper
    {
        //存放样式的集合
        private static readonly ConcurrentDictionary<string, ICellStyle> _cacheCellStyles = new ConcurrentDictionary<string, ICellStyle>();

        public static void CreateSheet(IWorkbook workBook, SheetConfigDto sheetConfigDto, IEnumerable<SheetCellDto> sheetCellList,
            List<(int columnIndex, int? minWidth, int? maxWidth)>? columnWidths = null)
        {
            var sheet = workBook.CreateSheet(sheetConfigDto.Name);
            //禁用网格线
            sheet.DisplayGridlines = sheetConfigDto.DisplayGridlines;
            //设置列宽
            SetColumnWidth(sheet, columnWidths);
            foreach (var rowCells in sheetCellList.OrderBy(t => t.Row).GroupBy(t => t.Row))
            {
                var row = sheet.CreateRow(rowCells.Key);
                //设置宽度为当前行中最大宽度的值
                var maxRowHeight = rowCells.Max(t => t.Height);
                if (maxRowHeight > 20) row.Height = (short)maxRowHeight;
                foreach (var item in rowCells)
                {
                    var excelCell = row.CreateCell(item.Column);
                    excelCell.SetCellType(item.CellType);
                    excelCell.SetCellValue(item.Value);
                    excelCell.CellStyle = CreateCellStyle(workBook, item.BaseCellStyle);

                    //合并
                    if (item.MergeConfig != null)
                    {
                        sheet.AddMergedRegionUnsafe(item.MergeConfig.GetCellRangeAddress(item.Row, item.Column));
                    }
                }
            }
        }

        /// <summary>
        /// 设置列宽度
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="columns"></param>
        private static void SetColumnWidth(ISheet sheet, List<(int columnIndex, int? minWidth, int? maxWidth)>? columns)
        {
            if (columns == null || columns.Count == 0)
                return;

            foreach (var (columnIndex, minWidth, maxWidth) in columns)
            {
                sheet.AutoSizeColumn(columnIndex);
                if (!minWidth.HasValue && !maxWidth.HasValue)
                    continue;

                var width = (int)(sheet.GetColumnWidth(columnIndex) * 1.2);

                if (minWidth.HasValue && width < minWidth)
                {
                    width = minWidth.Value;
                    sheet.SetColumnWidth(columnIndex, width);
                }
                else if (maxWidth.HasValue && width > maxWidth)
                {
                    width = maxWidth.Value;
                    sheet.SetColumnWidth(columnIndex, width);
                }
            }
        }

        /// <summary>
        ///创建单元格样式
        /// </summary>
        /// <param name="workBook"></param>
        /// <param name="style"></param>
        /// <returns></returns>
        private static ICellStyle CreateCellStyle(IWorkbook workBook, BaseCellStyle style)
        {
            return _cacheCellStyles.GetOrAdd(style.ToString(), (_) =>
            {
                var cellStyle = workBook.CreateCellStyle();
                cellStyle.Alignment = style.Alignment;
                var font = workBook.CreateFont();
                font.IsBold = style.IsBold;
                font.FontName = style.FontName;
                font.FontHeightInPoints = style.FontSize;
                font.Color = style.FontColor;
                cellStyle.SetFont(font);
                cellStyle.VerticalAlignment = style.VerticalAlignment;
                cellStyle.WrapText = style.WrapText;

                cellStyle.BorderBottom = style.BorderBottom;
                cellStyle.BorderLeft = style.BorderLeft;
                cellStyle.BorderRight = style.BorderRight;
                cellStyle.BorderTop = style.BorderTop;
                cellStyle.BottomBorderColor = style.BottomBorderColor;
                cellStyle.LeftBorderColor = style.LeftBorderColor;
                cellStyle.RightBorderColor = style.TopBorderColor;
                cellStyle.TopBorderColor = style.TopBorderColor;
                if (style.FillForegroundColor.HasValue)
                {
                    cellStyle.FillPattern = FillPattern.SolidForeground;
                    cellStyle.FillForegroundColor = style.FillForegroundColor.Value;
                }

                return cellStyle;
            });
        }
    }
}